package cn.tedu.anno;/**
 * @Author 金帮嘉诚 @Date 2021-06-24 星期四 14:06
 */
/*本类用于测试自定义注解，熟悉注解相关的规则*/

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 知识点
 */
public class TestAnnotation {
    public static void main(String[] args) {

    }
}

/*0.首先注意：自定义注解的语法与java不同，不要套用java的格式*/
//1.
/*1.注解定义要使用“@interface 注解名”的方式来定义*/

/*1.1需要通过@Target注解来描述当前自定义注解可以使用的位置
 * 注意@Target注解使用的时候需要导包，它的值通过“ElementType.静态常量”
 * 如“ElementType.METHOD,ElementType.FIELD”来指定
 * 如果需要指定多个值，可以使用{，}的格式来写*/
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
/*1.2通过@Retention注解表明此自定义注解的生命周期
 * 注意：@Retention使用时也需要导包
 * 它的值通过“RetentionPolicy.静态常量”来指定
 * 也就是自定义注解可以存活多久：源文件中/字节码文件中/运行时
 * 而且，这三个值只能选一个，不能写多个*/
@Retention(RetentionPolicy.SOURCE)
@interface Test {
    /*3.自定义注解可以添加功能--给自定义注解添加属性
     * 注意：int age();不是方法的定义，而是自定义注解中定义age属性的语法
     * 如果为了使用时方便，还可以给属性指定默认值，这样注解就可以不赋值直接使用*/
    //普通的属性
    int age() default 0;

    /*4.注解中还可以添加功能，可以定义特殊属性value
     * 特殊属性的定义与其他普通属性的定义相同，主要是使用方式不同
     * 使用此注解时，属性赋值不再需要写属性名，直接写值就可以
     * 也就是说：@Test(value = "apple")可以简写@Test("apple")
     * 但是自定义注解中的特殊属性赋予默认值时的格式不能简写
     * 如果给特殊属性赋予了默认值，使用了可以不赋值，使用默认值即可
     * */
    //如果注解定义中有多个方法，并且除了value以外的所有方法全部都默认值，
    //此时也可以在调用注解的时候，省去“value =”而直接对value进行赋值。
    String value() default "lemon";

}

/*2.使用注解时，在自定义注解名字前加@符号即可使用此注解*/
//没有在Target中添加TYPE时，报错not applicable to type
//@Test
class TestAnno {
    /*测试1：分别给TestAnno类/name属性/eat方法都添加了@Test注解，只有方法上不报错
     * 结论：自定义注解能够加在什么位置取决于@Target注解的值*/

    /* 测试2：修改@Target注解的值：
     * @Target({ElementType.METHOD, ElementType.FIELD,ElementType.TYPE})
     * 结论：注解@Target可以存在于多个位置，如果有多个值，格式为{，}
     * 原因：Target注解的源码：ElementType[] values();
     * */
//    @Test
    String name;

    /*测试3：当我们添加了注解的age属性后，@Test注解报错
     * 结论：当没有给自定义注解定义属性时，可以直接使用，但是如果有注解了，必须给属性赋值
     */

    /* 测试4：给@Test注解的属性赋值以后，就不报错了
    * 结论：给属性赋值的格式“@Test（age=18）”，注意不能直接写值，这是错误的格式
    * * /

    /* 测试5：给age属性赋值以后，可以不加属性值直接使用注解，
    * 此时使用的属性值是age的默认值
    * */
    /*测试6.给特殊属性value赋值时可以简写，相当于value="apple"*/
    //    @Test(value = "apple")
//    @Test("apple")
    /*测试7.因为两个属性均被设置默认值，所以无需赋值，可以使用@Test注解*/
    @Test
    public void eat() {
        System.out.println("点个哈哈哈");
    }
}
